using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace exenay{
public class Image
{
    private Texture2D tex;
    private Vector2 pos=Vector2.Zero;
    private Vector2 scale=new Vector2(1.0f, 1.0f);
    private float rot=0.0;
    private bool vertical;
    private bool horizontal;
    public Image(string imgPath,int x, int y)
    {
        tex=Content.Load<Texture2D>(imgPath);
        pos.X=x;
        pos.Y=y;
    }
    public flip(bool v, bool h){ vertical=v; horizontal=h;}
    public Texture2D getTexture(){
        
        else{
        return tex;}
    }
    public Tuple<int, int> getPos(){return Tuple<int, int>(pos.x,pos.y);}
    public void setPos(int x, int y)
    {
        pos.X=x;
        pos.Y=y;
    }
    public void setScale(int x, int y)
    {
        scale.X=x;
        scale.Y=y;
    }
    public Tuple<int, int> getScale(){return Tuple<int, int>(scale.x,scale.y);}
    public float getRot(){return rot;}
    public void setRot(float rad)
    {
        rot=rad % (3.14159265*2);
    }
    public void draw(){Game.draw(this);}
}
public class Animation
{
    private Texture2D tex;
    private Vector2 pos=Vector2.Zero;
    private Vector2 scale=new Vector2(1.0f, 1.0f);
    private float rot=0.0;
    private bool vertical;
    private bool horizontal;
    private float timer=0f; //timer
    private float speed; //speed in milliseconds
    private Point frames; //how many frames there are
    private Point frameSize; //size of each frame
    private Point currentFrame; //point on the frame thats being displayed
    public boolean Go=false; //play or pause animation, false=pause
    private Rectangle rect;
    public Animation(string imgPath,int x, int y,Point fc,float s)
    {
        tex=Content.Load<Texture2D>(imgPath);
        pos.X=x;
        pos.Y=y;
        frames=fc;
        speed=s;
        Game.anims.Add(this);
    }
    public step()
    {
        if (Go==true){
        timer+=(float)gameTime.ElapsedGameTime.TotalMilliseconds;
        if(currentFrame.x<=frames.x)
        {
            if(timer &gt; speed)
            {
                currentFrame.x++;
                timer=0f;
            }
        }
        if(currentFrame.x>frames.x)
        {
            currentFrame.x=0;
            currentFrame.y++;
        }
        if(currentFrame.y>frames.y)
        {
            currentFrame.y=0;
            currentFrame.x=0;
        }
        rect=new Rectangle(currentFrame.x*frameSize.x,currentFrame.y*frameSize.y,frameSize.x,frameSize.y);
        }
    }
    public flip(bool v, bool h){ vertical=v; horizontal=h;}
    public Texture2D getTexture(){return tex;}
    public Tuple<int, int> getPos(){return Tuple<int, int>(pos.x,pos.y);}
    public void setPos(int x, int y)
    {
        pos.X=x;
        pos.Y=y;
    }
    public void setScale(int x, int y)
    {
        scale.X=x;
        scale.Y=y;
    }
    public Tuple<int, int> getScale(){return Tuple<int, int>(scale.x,scale.y);}
    public float getRot(){return rot;}
    public void setRot(float rad)
    {
        rot=rad % (3.14159265*2);
    }
    public int getSpeed(){return speed;}
    public int set
    public void draw()
    {
        Game.drawAnim(this);
    }
    ~Animation()
    {
        for(int i=0; k<Game.anims.Count; i++)
        {
            if (Game.anims[i]==this)
            {
                anims.Delete(i);
                
            }
        }
    }
}
public class Game
{
    public List<Animation> anims = new List<Animation>();
    public State currentState=new State();
    batch=new SpriteBatch(GraphicsDevice);
    public Game(width,height){} //todo: initialize screen, enable shading
    public void animSteps()
    {
        for (int i = 0; i < list.Count; i++)
        {
            anims[i].step();
    }
    public void draw(Image image)
    {
        Texture2D tex;
        if(vertical==true || horizontal==true){
        Texture2D flipped = image.tex;
        Color[] data = new Color[source.Width * source.Height];
        Color[] flippedData = new Color[data.Length];
        source.GetData<color>(data);
        for (int x = 0; x < source.Width; x++)
          for (int y = 0; y < source.Height; y++)
          {
             int idx = (horizontal ? source.Width - 1 - x : x) +((vertical ? source.Height - 1 - y : y) * source.Width);
             flippedData[x + y * source.Width] = data[idx];
          }
        flipped.SetData<color>(flippedData);
        tex=flipped;}
        else
        {tex=image.getTexture()}
        batch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
        batch.Draw(tex,image.getPos(),Color.White,image.getRot(),image.getPos(),image.getScale(),SpriteEffects.None,0f);
        batch.End();
    }
    public void drawAnim(Animation anim)
    {
        Texture2D tex;
        if(anim.vertical==true || anim.horizontal==true){
        Texture2D flipped = anim.tex;
        Color[] data = new Color[source.Width * source.Height];
        Color[] flippedData = new Color[data.Length];
        source.GetData<color>(data);
        for (int x = 0; x < source.Width; x++)
          for (int y = 0; y < source.Height; y++)
          {
             int idx = (horizontal ? source.Width - 1 - x : x) +((vertical ? source.Height - 1 - y : y) * source.Width);
             flippedData[x + y * source.Width] = data[idx];
          }
        flipped.SetData<color>(flippedData);
        tex=flipped;}
        else
        {tex=anim.getTexture()}
        batch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
        batch.Draw(tex,anim.getPos(),anim.rect,Color.White,anim.getRot(),anim.getPos(),anim.getScale(),SpriteEffects.None,0f);
        batch.End();
    }
}
public class State
{
    public bool isLoaded=false;
    public virtual void load(){}
    public virtual void update(GameTime dt){}
    public virtual void draw(GameTime dt){}
}
protected override void LoadContent(){Game.currentState.load();}
protected override void Update(dt)
{
    if(Game.currentState.isLoaded==true){Game.currentState.update(dt);}
    else
    {
        Game.currentState.load();
        Game.currentState.isLoaded=true;
        Game.currentState.update(dt);
    }
    Game.animSteps();
}
protected override void Draw(GameTime dt){Game.currentState.draw(dt);}
}
